2023/12/234875字符
Hook
所有 Hook 不能写在 if | for 中
State Hook
- State Hook 是一个在函数组件中使用的函数(useState),用于在函数组建中使用状态
import React, {useState} from 'react';
import ReactDOM from 'react-dom';
function Comp () {
// useState() 返回一个数组,arr[0] 初始值,arr[1] 设置值
let [num, setNum] = useState(0);
setNum = 0; // 两次数据完全相等(Object.is 进行比较),不会导致重新渲染
return (<>{setNum}</>)
}
ReactDOM.render(<Comp />, document.getElementById('root'));
一个函数组件中可以有多个状态,这种做法非常有利于横向切分关注点
Effect Hook
import React, {useState, useEffect} from 'react';
import ReactDOM from 'react-dom';
function Comp () {
let [num, setNum] = useState(0);
useEffect(() => { // 副作用操作
document.title = num;
let timer = setInterval(() => {
console.log(num + 1);
}, 1000);
// 返回函数,永远执行在 useEffect 的最开始(在数据初始化时不会执行)
return () => {
clearInterval(timer);
timer = null;
}
}, [num]) // 第二个参数会与原先数据进行比较,一致则不会运行 useEffect
return (<h1 onClick={() => {
setNum(num + 1);
}}>{num}</h1>)
}
ReactDOM.render(<Comp />, document.getElementById('root'));
副作用函数的运行时间在真实 UI 渲染完之后,是异步操作,不会阻塞页面
LayoutEffect Hook
- useLayoutEffect 完成了 DOM 渲染,但还没呈现页面
import React, {useState, useLayoutEffect} from 'react';
import ReactDOM from 'react-dom';
function Comp () {
const [num,] = useState(10);
useLayoutEffect(() => {
console.log(num);
})
return (<h1>hello</h1>)
}
ReactDOM.render(<Comp />, document.getElementById('root'));
Context Hook
import React, {useContext} from 'react';
import ReactDOM from 'react-dom';
const ctx = React.createContext('hello');
function Comp () {
const value = useContext(ctx);
return (<h1>{value}</h1>)
}
ReactDOM.render(<Comp />, document.getElementById('root'));
Callback Hook
import React, {useState, useCallback} from 'react';
import ReactDOM from 'react-dom';
function Comp () {
const [num, setNum] = useState(10);
const handleClick = useCallback(() => {
setNum(num + 1);
}, [num])
return (<h1 onClick={handleClick}>{num}</h1>)
}
ReactDOM.render(<Comp />, document.getElementById('root'));
Memo Hook
import React, {useState, useMemo} from 'react';
import ReactDOM from 'react-dom';
function Comp () {
const [, setN] = useState(0);
const [range,] = useState({min: 0, max: 100});
const list = useMemo(() => {
const arr = [];
for (let i = 0; i < range.max; i++) {
console.log(i)
arr.push(<li key={i}>{i}</li>);
}
return arr;
}, [range]) // 监控 range 状态
return (<ul onClick={() => {
setN(10); // 改变了 setN 的值,不会导致 range 重新渲染,达到性能上的优化
}}>
{list}
</ul>)
}
ReactDOM.render(<Comp />, document.getElementById('root'));
Ref Hook
import React, {useRef, useEffect} from 'react';
import ReactDOM from 'react-dom';
function Comp () {
const demo = useRef();
useEffect(() => {
console.log(demo.current);
})
return (<h1 ref={demo}>hello</h1>)
}
ReactDOM.render(<Comp />, document.getElementById('root'));
ImperativeHandle Hook
import React, {useRef, useImperativeHandle, useEffect} from 'react';
import ReactDOM from 'react-dom';
const TestSomComp = React.forwardRef(SonComp);
function Comp () {
const demo = useRef();
return (<>
<h1 onClick={() => {
demo.current.method();
}}>hello</h1>
<TestSomComp ref={demo}/>
</>)
}
function SonComp (props, ref) {
useImperativeHandle(ref, () => {
return {
method () {
console.log(123456)
}
}
}, [])
return <h2>word</h2>
}
ReactDOM.render(<Comp />, document.getElementById('root'));
DebugValue Hook
import React, {useState, useDebugValue} from 'react';
import ReactDOM from 'react-dom';
// 自定义 Hook
function useTest () {
const [num,] = useState(10);
useDebugValue(num); // 方便调试,展示关键信息
return num;
}
function Comp () {
useTest();
return (<h1>hello</h1>)
}
ReactDOM.render(<Comp />, document.getElementById('root'));